# -*- coding: utf-8 -*-
"""
文件分享模型
@api-version: 1.0.0
// REF: API-NETDISK-003
"""

from datetime import datetime, timedelta
from . import db
from .user import User
from .virtual_file import VirtualFile
import secrets
import string

class FileShare(db.Model):
    """文件分享模型
    
    用于管理文件的分享功能
    支持密码保护和过期时间设置
    """
    __tablename__ = 'file_shares'
    
    id = db.Column(db.Integer, primary_key=True, comment='分享ID')
    share_id = db.Column(db.String(32), unique=True, nullable=False, comment='分享唯一标识')
    file_id = db.Column(db.Integer, db.ForeignKey('virtual_files.id'), nullable=False, comment='虚拟文件ID')
    owner_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False, comment='分享者用户ID')
    share_password = db.Column(db.String(20), comment='分享密码（可选）')
    access_count = db.Column(db.Integer, default=0, comment='访问次数')
    download_count = db.Column(db.Integer, default=0, comment='下载次数')
    expires_at = db.Column(db.DateTime, comment='过期时间（NULL=永久）')
    is_active = db.Column(db.Boolean, default=True, comment='是否有效')
    created_at = db.Column(db.DateTime, nullable=False, default=datetime.utcnow, comment='创建时间')
    
    # 关联关系
    file = db.relationship('VirtualFile', backref='shares')
    owner = db.relationship('User', backref='file_shares')
    
    # 表级约束
    __table_args__ = (
        db.CheckConstraint('access_count >= 0', name='chk_shares_access_count'),
        db.CheckConstraint('download_count >= 0', name='chk_shares_download_count'),
    )
    
    def __init__(self, file_id, owner_id, expire_hours=None, password=None):
        self.share_id = self._generate_share_id()
        self.file_id = file_id
        self.owner_id = owner_id
        self.share_password = password
        self.access_count = 0
        self.download_count = 0
        self.is_active = True
        
        # 设置过期时间
        if expire_hours:
            self.expires_at = datetime.utcnow() + timedelta(hours=expire_hours)
        else:
            self.expires_at = None
    
    @staticmethod
    def _generate_share_id():
        """生成分享ID"""
        # 生成8位随机字符串
        characters = string.ascii_letters + string.digits
        while True:
            share_id = ''.join(secrets.choice(characters) for _ in range(8))
            # 确保唯一性
            if not FileShare.query.filter_by(share_id=share_id).first():
                return share_id
    
    def is_expired(self):
        """检查是否已过期"""
        if not self.expires_at:
            return False
        return datetime.utcnow() > self.expires_at
    
    def is_valid(self):
        """检查分享是否有效"""
        return self.is_active and not self.is_expired()
    
    def check_password(self, password):
        """检查分享密码"""
        if not self.share_password:
            return True  # 无密码保护
        return self.share_password == password
    
    def increment_access(self):
        """增加访问计数"""
        self.access_count += 1
        db.session.commit()
    
    def increment_download(self):
        """增加下载计数"""
        self.download_count += 1
        db.session.commit()
    
    def deactivate(self):
        """取消分享"""
        self.is_active = False
        db.session.commit()
    
    def extend_expiry(self, hours):
        """延长过期时间"""
        if self.expires_at:
            self.expires_at = max(self.expires_at, datetime.utcnow()) + timedelta(hours=hours)
        else:
            self.expires_at = datetime.utcnow() + timedelta(hours=hours)
        db.session.commit()
    
    def get_share_url(self, base_url="http://localhost:3000"):
        """获取分享链接"""
        return f"{base_url}/share/{self.share_id}"
    
    def get_remaining_time(self):
        """获取剩余时间（秒）"""
        if not self.expires_at:
            return None
        
        remaining = self.expires_at - datetime.utcnow()
        return max(0, int(remaining.total_seconds()))
    
    def get_formatted_remaining_time(self):
        """获取格式化的剩余时间"""
        remaining_seconds = self.get_remaining_time()
        if remaining_seconds is None:
            return "永久有效"
        
        if remaining_seconds <= 0:
            return "已过期"
        
        days = remaining_seconds // 86400
        hours = (remaining_seconds % 86400) // 3600
        minutes = (remaining_seconds % 3600) // 60
        
        if days > 0:
            return f"{days}天{hours}小时"
        elif hours > 0:
            return f"{hours}小时{minutes}分钟"
        else:
            return f"{minutes}分钟"
    
    @staticmethod
    def create_share(file_id, owner_id, expire_hours=None, password=None):
        """创建文件分享"""
        # 检查文件是否存在且属于用户
        file_obj = VirtualFile.query.filter_by(id=file_id, owner_id=owner_id).first()
        if not file_obj:
            raise ValueError("文件不存在或无权限")
        
        if file_obj.is_folder:
            raise ValueError("暂不支持分享文件夹")
        
        # 检查是否已有有效分享
        existing_share = FileShare.query.filter_by(
            file_id=file_id,
            owner_id=owner_id,
            is_active=True
        ).filter(
            db.or_(
                FileShare.expires_at.is_(None),
                FileShare.expires_at > datetime.utcnow()
            )
        ).first()
        
        if existing_share:
            return existing_share
        
        # 创建新分享
        share = FileShare(
            file_id=file_id,
            owner_id=owner_id,
            expire_hours=expire_hours,
            password=password
        )
        
        db.session.add(share)
        db.session.commit()
        
        return share
    
    @staticmethod
    def get_by_share_id(share_id):
        """根据分享ID获取分享"""
        return FileShare.query.filter_by(share_id=share_id).first()
    
    @staticmethod
    def get_user_shares(owner_id, page=1, page_size=20, include_expired=False):
        """获取用户的分享列表"""
        query = FileShare.query.filter_by(owner_id=owner_id)
        
        if not include_expired:
            query = query.filter(
                db.and_(
                    FileShare.is_active == True,
                    db.or_(
                        FileShare.expires_at.is_(None),
                        FileShare.expires_at > datetime.utcnow()
                    )
                )
            )
        
        query = query.order_by(FileShare.created_at.desc())
        
        return query.paginate(
            page=page,
            per_page=page_size,
            error_out=False
        )
    
    @staticmethod
    def cleanup_expired_shares():
        """清理过期的分享"""
        expired_shares = FileShare.query.filter(
            db.and_(
                FileShare.expires_at.isnot(None),
                FileShare.expires_at <= datetime.utcnow(),
                FileShare.is_active == True
            )
        ).all()
        
        count = 0
        for share in expired_shares:
            share.is_active = False
            count += 1
        
        if count > 0:
            db.session.commit()
        
        return count
    
    def to_dict(self, include_file_info=True, include_sensitive=False):
        """转换为字典格式"""
        data = {
            'id': self.id,
            'shareId': self.share_id,
            'fileId': self.file_id,
            'ownerId': self.owner_id,
            'hasPassword': bool(self.share_password),
            'accessCount': self.access_count,
            'downloadCount': self.download_count,
            'expiresAt': self.expires_at.isoformat() if self.expires_at else None,
            'isActive': self.is_active,
            'isExpired': self.is_expired(),
            'isValid': self.is_valid(),
            'createdAt': self.created_at.isoformat() if self.created_at else None,
            'shareUrl': self.get_share_url(),
            'remainingTime': self.get_remaining_time(),
            'formattedRemainingTime': self.get_formatted_remaining_time()
        }
        
        # 包含文件信息
        if include_file_info and self.file:
            file_data = self.file.to_dict()
            data.update({
                'fileName': file_data.get('name'),
                'fileSize': file_data.get('fileSize'),
                'formattedSize': file_data.get('formattedSize'),
                'mediaType': file_data.get('mediaType'),
                'mediaTypeName': file_data.get('mediaTypeName'),
                'fileExtension': file_data.get('fileExtension'),
                'largeIconUrl': file_data.get('largeIconUrl'),
                'smallIconUrl': file_data.get('smallIconUrl')
            })
        
        # 敏感信息（仅在需要时包含）
        if include_sensitive:
            data['sharePassword'] = self.share_password
        
        return data
    
    def __repr__(self):
        return f'<FileShare {self.share_id}:{self.file_id} (owner:{self.owner_id})>'